package com.qkl.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.qkl.user.dto.InvitationUserDto;
import com.qkl.user.dto.user.LevelStatDto;
import com.qkl.user.entity.MatrixRelation;
import com.qkl.user.entity.User;
import com.qkl.user.entity.UserLevel;
import com.qkl.user.enums.TalentLevelEnum;
import com.qkl.user.enums.UserLevelEnum;
import com.qkl.user.exception.OperationException;
import com.qkl.user.mapper.InvitationRelationMapper;
import com.qkl.user.mapper.MatrixRelationMapper;
import com.qkl.user.mapper.UserLevelMapper;
import com.qkl.user.mapper.UserMapper;
import com.qkl.user.service.MatrixService;
import com.qkl.user.utils.JwtUtils;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
@Slf4j
@Service
public class MatrixServiceImpl implements MatrixService {

    @Autowired
    private MatrixRelationMapper matrixRelationMapper;
    @Autowired
    private UserLevelMapper userLevelMapper;

    @Autowired
    private InvitationRelationMapper invitationRelationMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    // 位置常量：左（直推1）、右（直推2）
    public static final int POSITION_LEFT = 1;  // 左位：第一个直推（唯一允许的直推位）
    public static final int POSITION_RIGHT = 2; // 右位：第二个直推（保留但不参与滑落分配）
    @Autowired
    private UserMapper userMapper;

    /**
     * 查询某个节点的总人数（自身+所有子节点，无限层级）
     * @return 总人数
     */
    public long queryTotalUserCount() {

       log.info("查询getByDirectCount={}", TalentLevelEnum.getByDirectCount(5));

       Long nodeUserId = JwtUtils.getUserId();
        // 校验节点是否存在
        MatrixRelation node = matrixRelationMapper.selectByUserId(nodeUserId);
        if (node == null) {
            log.warn("节点用户[{}]不存在", nodeUserId);
            return 0;
        }
        // 1. 调用已有方法，获取1~16层每层人数
        List<LevelStatDto> levelStatList = query16LevelUserCount();

        // 2. 求和所有层级的人数（即总节点数）
        return levelStatList.stream()
                .mapToLong(LevelStatDto::getUserCount) // 提取每层人数
                .sum(); // 累加总人数
        // 递归统计所有子节点（深度优先遍历）
        //return countAllChildren(node);
    }




    /**
     * 递归统计所有子节点（含自身）
     */
    private long countAllChildren(MatrixRelation current) {
        if (current == null) {
            return 0;
        }

        // 自身计数1，加上左子节点的所有后代
        long count = 1;
        MatrixRelation leftChild = matrixRelationMapper.selectByUserId(current.getLeftChildId());
        count += countAllChildren(leftChild);

        // 右子节点是自身直推，也计入总人数（按公排逻辑，右子节点的后代也属于该节点伞下）
        MatrixRelation rightChild = matrixRelationMapper.selectByUserId(current.getRightChildId());
        count += countAllChildren(rightChild);

        return count;
    }
    /**
     * 为新用户分配公排位置（完全贴合你的逻辑：直推2个后，按a-1→a-2→a-1-1→a-2-1顺序滑落）
     */
    public void assignMatrixPosition(Long newUserId, Long inviterUserId, String username) {
        // 1. 校验新用户是否已在公排（原有）
        MatrixRelation existing = matrixRelationMapper.selectByUserId(newUserId);
        if (existing != null) {
            log.warn("用户[{}]已在公排，无需重复分配", newUserId);
            return;
        }

        // 2. 校验邀请人是否存在公排记录（原有）
        MatrixRelation inviterMatrix = matrixRelationMapper.selectByUserId(inviterUserId);
        if (inviterMatrix == null) {
            throw new OperationException(-1, "邀请用户公排位置分配失败");
        }

        // 3. 核心逻辑：优先填充自身左/右位（直推），满则触发滑落（原有）
        MatrixRelation targetParent;
        if (inviterMatrix.getLeftChildId() == null) {
            targetParent = inviterMatrix;
        } else if (inviterMatrix.getRightChildId() == null) {
            targetParent = inviterMatrix;
        } else {
            targetParent = findSlidePosition(inviterMatrix);
        }

        if (targetParent == null) {
            throw new OperationException(-1, "未找到可用公排位置");
        }

        // 4. 确定位置（原有）
        int position;
        if (targetParent.getUserId().equals(inviterUserId)) {
            position = targetParent.getLeftChildId() == null ? POSITION_LEFT : POSITION_RIGHT;
        } else {
            position = POSITION_LEFT;
        }

        // 5. 并发校验（原有）
        if ((position == POSITION_LEFT && targetParent.getLeftChildId() != null) ||
                (position == POSITION_RIGHT && targetParent.getRightChildId() != null)) {
            throw new OperationException(-1, "位置已被占用，请重试");
        }

        // 6. 创建新用户公排记录（核心优化：path生成逻辑）
        MatrixRelation newMatrix = new MatrixRelation();
        newMatrix.setUserId(newUserId);
        newMatrix.setParentId(targetParent.getUserId());
        newMatrix.setPosition(position);
        newMatrix.setLevel(targetParent.getLevel() + 1); // 层级=父层级+1

        // 【核心优化1：path格式为“正向路径（用户ID拼接）”，如“1001-1002-1005”】
        String parentPath = targetParent.getPath();
        if (parentPath == null || parentPath.isEmpty()) {
            // 根节点path：直接用自身用户ID（如A的用户ID=1001→path="1001"）
            newMatrix.setPath(String.valueOf(newUserId));
        } else {
            // 子节点path：父节点path + "-" + 自身用户ID（如a1的path="1001-1002"）
            newMatrix.setPath(parentPath + "-" + newUserId);
        }

        // 新节点初始无子女，childIndex为空（原有）
        newMatrix.setChildIndex("");

        matrixRelationMapper.insert(newMatrix);
        log.info("新用户[{}]公排记录创建，path={}", newUserId, newMatrix.getPath());

        // 7. 更新父节点的子节点引用 + 维护childIndex（原有逻辑）
        if (position == POSITION_LEFT) {
            targetParent.setLeftChildId(newUserId);
        } else {
            targetParent.setRightChildId(newUserId);
        }

        // 更新父节点的childIndex（拼接新子节点ID）
        updateParentChildIndex(targetParent, newUserId);

        matrixRelationMapper.updateById(targetParent);
        log.info("用户[{}]分配到[{}]的{}位", newUserId, targetParent.getUserId(),
                position == POSITION_LEFT ? "左" : "右");
    }

    /**
     * 滑落逻辑（原有，无修改）
     */
    private MatrixRelation findSlidePosition(MatrixRelation inviter) {
        if (inviter == null) {
            return null;
        }

        // 1. 获取邀请人的两个直推：a-1（左）、a-2（右）
        MatrixRelation a1 = matrixRelationMapper.selectByUserId(inviter.getLeftChildId());
        MatrixRelation a2 = matrixRelationMapper.selectByUserId(inviter.getRightChildId());
        if (a1 == null || a2 == null) {
            throw new OperationException(-1, "邀请人需先拥有2个直推才能滑落");
        }

        // 2. 用队列实现顺序遍历：a1→a2→a1的左子→a2的左子→a1的左子的左子→…
        Queue<MatrixRelation> queue = new LinkedList<>();
        queue.offer(a1); // 第1个检查：a-1
        queue.offer(a2); // 第2个检查：a-2

        while (!queue.isEmpty()) {
            MatrixRelation current = queue.poll();
            if (current == null) {
                continue;
            }

            // 关键：仅左位为空（无直推）的节点可作为滑落父节点
            if (current.getLeftChildId() == null) {
                return current;
            }

            // 若当前节点有直推（左位不为空），将其左子节点加入队列（后续检查）
            MatrixRelation leftChild = matrixRelationMapper.selectByUserId(current.getLeftChildId());
            if (leftChild != null) {
                queue.offer(leftChild);
            }
        }

        // 所有节点均有直推（左位满）→无可用位置
        return null;
    }


    /**
     * 辅助方法：更新父节点的childIndex（原有，无修改）
     */
    private void updateParentChildIndex(MatrixRelation parent, Long newChildUserId) {
        String oldChildIndex = parent.getChildIndex();
        StringBuilder newChildIndex = new StringBuilder();

        if (oldChildIndex != null && !oldChildIndex.isEmpty()) {
            newChildIndex.append(oldChildIndex).append(",");
        }
        newChildIndex.append(newChildUserId);

        parent.setChildIndex(newChildIndex.toString());
        log.info("父节点[{}]childIndex更新为：{}", parent.getUserId(), newChildIndex);
    }
    /**
     * 初始化根节点公排记录
     */
    private MatrixRelation initRootMatrix(Long userId) {
        // 创建根节点（path="1"，level=1，position=0）
        MatrixRelation root = new MatrixRelation();
        root.setUserId(userId);
        root.setParentId(0L); // 根节点父ID为0
        root.setPosition(0); // 根节点位置为0
        root.setLevel(1); // 根节点层级为1
        root.setPath("1"); // 根节点path为"1"
        root.setChildIndex(""); // 初始无子女
        root.setLeftChildId(null);
        root.setRightChildId(null);

        matrixRelationMapper.insert(root);
        return root;
    }

    /**
     * 构建空统计列表（1~16层均为0人）
     */
    private List<LevelStatDto> buildEmptyStatList() {
        List<LevelStatDto> statList = new ArrayList<>(16);
        for (int level = 1; level <= 16; level++) {
            LevelStatDto stat = new LevelStatDto();
            stat.setLevel(level);
            stat.setUserCount(0L);
            stat.setHighestLevel("");
            statList.add(stat);
        }
        return statList;
    }
    /**
     * 查询指定用户伞下1~16层的每层人数（修正：直推为第一层，不含自身）
     * @return 1~16层统计列表（level=层级，userCount=人数）
     */
//    public List<LevelStatDto> query16LevelUserCount() {
//        Long targetUserId = JwtUtils.getUserId();
//        // 1. 获取目标用户的path（如A的path="1001"）
//        MatrixRelation targetNode = matrixRelationMapper.selectByUserId(targetUserId);
//        if (targetNode == null) {
//            log.warn("目标用户[{}]未在公排中，返回空统计", targetUserId);
//            throw new OperationException(-1, "目标用户未在公排中");
//            //return buildEmptyStatList();
//        }
//        String targetPath = targetNode.getPath();
//        int targetPathSegments = countPathSegments(targetPath); // 目标path的段数（如"1001"→1段）
//        log.info("目标用户[{}]path={}", targetUserId, targetPath);
//
//        // 2. 1次SQL捞出16层内所有子树节点（仅子节点，不含自身！核心修正）
//        List<String> childPaths = matrixRelationMapper.selectChildPathsByPrefixAndMaxSegments(
//                targetPath, targetPathSegments + 16 // 最大段数=目标段数+16（16层）
//        );
//        log.info("用户[{}]的子树path列表：{} 目标段数 {}", targetUserId, childPaths,targetPathSegments);
//        if (CollectionUtils.isEmpty(childPaths)) {
//            log.warn("用户[{}]伞下16层无数据", targetUserId);
//            return buildEmptyStatList();
//        }
//        // 3. 按path段数分组（段数=层级），统计每层人数（修正层级计算逻辑）
//        Map<Integer, Long> levelCountMap = childPaths.stream()
//                .map(path -> {
//                    int segments = countPathSegments(path);
//                    log.info("path={} 段数 {}", path, segments);
//                    // 核心修正：相对层级 = 当前段数 - 目标段数（原+1，现在去掉）
//                    // 例：目标段数1（A的path="1001"），直推节点段数2→层级=2-1=1（第一层）
//                    return segments - targetPathSegments;
//                })
//                .filter(level -> level >= 1 && level <= 16) // 过滤1~16层（不含自身）
//                .collect(Collectors.groupingBy(//收集器，用于将元素按某个属性进行分组
//                        level -> level,
//                        Collectors.counting() // 统计每层人数
//                ));
//
//        // 4. 构建1~16层完整统计结果（无人的层级人数填0）
//        return buildLevelStatList(levelCountMap);
//    }


    /**
     * 查询指定用户伞下1~16层的每层人数及最高等级达人
     */
    public List<LevelStatDto> query16LevelUserCount() {
        Long targetUserId = JwtUtils.getUserId();

        // 1. 获取目标用户的path和段数
        MatrixRelation targetNode = matrixRelationMapper.selectByUserId(targetUserId);
        if (targetNode == null) {
            log.warn("目标用户[{}]未在公排中，返回空统计", targetUserId);
            throw new OperationException(-1, "目标用户未在公排中");
        }
        String targetPath = targetNode.getPath();
        int targetPathSegments = countPathSegments(targetPath);
        int maxSegments = targetPathSegments + 16; // 包含16层

        // 2. 1次SQL捞出16层内所有子节点的ID和path
        List<Map<String, Object>> childNodes = matrixRelationMapper.selectChildUserIdsAndPathsByPrefixAndMaxSegments(
                targetPath, maxSegments
        );
        if (CollectionUtils.isEmpty(childNodes)) {
            log.warn("用户[{}]伞下16层无数据", targetUserId);
            return buildEmptyStatList();
        }

        // 3. 按层级分组，收集每个层级的userIds
        Map<Integer, List<Long>> levelUserIdMap = new HashMap<>();
        for (Map<String, Object> node : childNodes) {
            String path = (String) node.get("path");
            Long userId = Long.valueOf(node.get("userId").toString());

            int segments = countPathSegments(path);
            int level = segments - targetPathSegments; // 计算相对层级

            if (level >= 1 && level <= 16) {
                levelUserIdMap.computeIfAbsent(level, k -> new ArrayList<>()).add(userId);
            }
        }

        // 4. 准备返回结果
        List<LevelStatDto> resultList = buildEmptyStatList();

        // 5. 遍历每个层级，计算人数和最高等级
        for (Map.Entry<Integer, List<Long>> entry : levelUserIdMap.entrySet()) {
            int level = entry.getKey();
            List<Long> userIds = entry.getValue();
            log.info("层级 {} 用户 {}", level, userIds);
            // 5.1 设置人数
            LevelStatDto statDto = resultList.get(level - 1); // list是0-based索引
            statDto.setUserCount((long) userIds.size());

            // 5.2 查询该层级所有用户的等级信息和达人等级，确定最高等级
             String highestCombinedLevel = findHighestCombinedLevelInLevel(userIds);
            statDto.setHighestLevel(highestCombinedLevel);
        }

        return resultList;
    }

    @Override
    public Boolean isInNode(String address) {
         Long targetUserId = JwtUtils.getUserId();
         User user = userMapper.getUserByAddress(address);
         if (user==null){
             throw new OperationException(-1, "输入地址用户不存在");
         }
        Long childUserId  = user.getId();
        if(targetUserId.equals(childUserId)){
           throw new OperationException(-1, "输入用户不能为登录用户");
        }
        int count =  matrixRelationMapper.isChildNode(targetUserId, childUserId);
        return count>0;
    }

    /**
     * 查找某一层级中所有用户的最高等级（等级+达人）
     * @param userIds 该层级的所有用户ID
     * @return 拼接后的最高等级名称，如 "二星中尉"
     */
    private String findHighestCombinedLevelInLevel(List<Long> userIds) {
        if (CollectionUtils.isEmpty(userIds)) {
            return UserLevelEnum.NO_LEVEL.getLevelName();
        }

        // 批量查询用户的等级名称 (假设从 user 表查询)
        UserLevel max_user = userLevelMapper.batchSelectLevelNamesByUserIds(userIds);
        if (max_user == null) {
            return UserLevelEnum.NO_LEVEL.getLevelName();
        }
        Long max_user_id = max_user.getUserId();
        // 拼接最高等级名称
        return getUserTalentLevel(max_user_id);//highestTalentEnum.getLevelName() + highestLevelEnum.getLevelName();
    }
    /**
     * 辅助方法：统计path的段数（如"1001-1002-1005"→3段）
     */
    private int countPathSegments(String path) {
        if (path == null || path.isEmpty()) {
            return 0;
        }
        return path.split("-").length;
    }

    /**
     * 构建1~16层统计结果
     */
    private List<LevelStatDto> buildLevelStatList(Map<Integer, Long> levelCountMap) {
        List<LevelStatDto> statList = new ArrayList<>(16);
        for (int level = 1; level <= 16; level++) {
            LevelStatDto stat = new LevelStatDto();
            stat.setLevel(level);
            // 存在该层级则取统计数，否则填0
            stat.setUserCount(levelCountMap.getOrDefault(level, 0L));
            stat.setHighestLevel(""); // 若需填充最高等级，可在此处调用之前的findHighestLevel方法
            statList.add(stat);
        }
        return statList;
    }
    public String getUserTalentLevel(Long userId){

        String cacheKey = "talent_level:" + userId;
        String cachedLevel = redisTemplate.opsForValue().get(cacheKey);
        if (cachedLevel != null) {
            return cachedLevel;
        }
        String expert = "";
        UserLevel userLevel = userLevelMapper.selectByUserId(userId);
        Integer userLevelPriority;
        if(userLevel == null){
            userLevelPriority = UserLevelEnum.NO_LEVEL.getPriority();
        }else {
            userLevelPriority = userLevel.getLevel();
            InvitationUserDto invitationUserDto = invitationRelationMapper.InvitationUser(userId);;
            int directCount = invitationUserDto.getTotalInviteCount();
            TalentLevelEnum talentLevel = TalentLevelEnum.getByDirectCount(directCount);
            expert = talentLevel.getLevelName();
        }
        String level = UserLevelEnum.getLevelNameByPriority(userLevelPriority);
        String finalLevel = expert+level;
        redisTemplate.opsForValue().set(cacheKey, finalLevel, 10, TimeUnit.MINUTES);
        return finalLevel;
    }

    /**
     * 批量获取用户的等级名称（达人等级 + 用户等级）
     * @param userIds 用户ID列表
     * @return Map<用户ID, 组合后的等级名称>
     */
    public Map<Long, String> batchGetUserTalentLevels(List<Long> userIds) {
        Map<Long, String> resultMap = new HashMap<>();
        List<Long> userIdsToQuery = new ArrayList<>();

        // 1. 先从缓存中获取，分离出需要查询数据库的用户ID
        for (Long userId : userIds) {
            String cacheKey = "talent_level:" + userId;
            String cachedLevel = redisTemplate.opsForValue().get(cacheKey);
            if (cachedLevel != null) {
                resultMap.put(userId, cachedLevel);
            } else {
                userIdsToQuery.add(userId);
            }
        }

        // 2. 如果所有用户都在缓存中，直接返回
        if (userIdsToQuery.isEmpty()) {
            return resultMap;
        }

        // 3. 批量查询这些用户的等级信息 (1次数据库查询)
        Map<Long, UserLevel> userLevelMap = userLevelMapper.batchSelectByUserIds(userIdsToQuery);

        // 4. 批量查询这些用户的直推人数 (1次数据库查询)
        Map<Long, InvitationUserDto> invitationUserMap = invitationRelationMapper.batchSelectInvitationUsers(userIdsToQuery);

        // 5. 在内存中循环处理，组装等级名称并写入缓存
        for (Long userId : userIdsToQuery) {
            String expert = "";
            UserLevel userLevel = userLevelMap.get(userId);
            Integer userLevelPriority = UserLevelEnum.NO_LEVEL.getPriority();

            if (userLevel != null) {
                userLevelPriority = userLevel.getLevel();

                // 获取直推人数
                InvitationUserDto invitationUserDto = invitationUserMap.get(userId);
                int directCount = (invitationUserDto != null) ? invitationUserDto.getTotalInviteCount() : 0;

                TalentLevelEnum talentLevel = TalentLevelEnum.getByDirectCount(directCount);
                expert = talentLevel.getLevelName();
            }

            String level = UserLevelEnum.getLevelNameByPriority(userLevelPriority);
            String finalLevel = expert + level;

            // 放入结果集和缓存
            resultMap.put(userId, finalLevel);
            redisTemplate.opsForValue().set("talent_level:" + userId, finalLevel, 10, TimeUnit.MINUTES);
        }

        return resultMap;
    }
}
